/*
 * Sales Data Controller Project.
 * Copyright (C) 2011 FedICT.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License version
 * 3.0 as published by the Free Software Foundation.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, see 
 * http://www.gnu.org/licenses/.
 */

package be.fedict.sdc.vsc.tlv;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * Holds TLV related metadata about a given Java class.
 * 
 * @author Frank Cornelis
 * 
 */
public class TLVMetadata {

	private final Class<?> tlvClass;

	private final Map<Integer, Field> tlvFieldsByTag;

	private final Map<Field, Integer> tlvFields;

	public TLVMetadata(Class<?> tlvClass) {
		this.tlvClass = tlvClass;
		this.tlvFieldsByTag = new HashMap<Integer, Field>();
		this.tlvFields = new HashMap<Field, Integer>();
		processClassMetadata();
	}

	public boolean canHandle(Class<?> clazz) {
		return this.tlvClass.equals(clazz);
	}

	private void processClassMetadata() {
		Field[] fields = this.tlvClass.getDeclaredFields();
		for (Field field : fields) {
			TLVField tlvFieldAnnotation = field.getAnnotation(TLVField.class);
			if (null == tlvFieldAnnotation) {
				continue;
			}
			int tag = tlvFieldAnnotation.value();
			if (this.tlvFieldsByTag.containsKey(tag)) {
				throw new RuntimeException("duplicate tag: " + tag
						+ " in class " + this.tlvClass.getName());
			}
			this.tlvFieldsByTag.put(tag, field);
			this.tlvFields.put(field, tag);
		}
	}

	public Field getField(int tag) {
		return this.tlvFieldsByTag.get(tag);
	}

	public int getTag(Field field) {
		return this.tlvFields.get(field);
	}

	public Set<Field> getFields() {
		return this.tlvFields.keySet();
	}
}
